package com.example.service.adm.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.constants.ErrorMsg;
import com.example.context.PageResult;
import com.example.entity.RoleDO;
import com.example.entity.UserDO;
import com.example.enums.RoleEnum;
import com.example.exception.exception;
import com.example.mapper.RoleMapper;
import com.example.mapper.UserMapper;
import com.example.service.adm.AdmUserService;
import com.example.utils.FileUtil;
import com.example.vo.user.AdmUserPageReqVO;
import com.example.vo.user.AdmUserPageRespVO;
import com.example.vo.user.UserAdmReqVO;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Locale;

@Service
public class AdmUserServiceImpl implements AdmUserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private FileUtil fileUtil;

    @Override
    public PageResult<AdmUserPageRespVO> list(AdmUserPageReqVO reqVO) {
        Page<UserDO> page = new Page<>(reqVO.getPage(), reqVO.getSize());
        LambdaQueryWrapper<UserDO> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(reqVO.getNickname())) {
            wrapper.like(UserDO::getNickname, reqVO.getNickname());
        }
        if (StringUtils.isNotBlank(reqVO.getUsername())) {
            wrapper.like(UserDO::getUsername, reqVO.getUsername());
        }
        if (StringUtils.isNotBlank(reqVO.getPhone())) {
            wrapper.like(UserDO::getPhone, reqVO.getPhone());
        }
        if (reqVO.getGender() != null) {
            wrapper.eq(UserDO::getGender, reqVO.getGender());
        }
        if (reqVO.getStatus() != null) {
            wrapper.eq(UserDO::getStatus, reqVO.getStatus());
        }
        wrapper.orderByDesc(UserDO::getCreateTime);
        IPage<UserDO> iPage = userMapper.selectPage(page, wrapper);
        List<AdmUserPageRespVO> res = iPage.getRecords().stream().map(user -> {
            AdmUserPageRespVO respVO = BeanUtil.copyProperties(user, AdmUserPageRespVO.class);
            respVO.setRoleName(roleMapper.getRoleByUserId(user.getId()).getName());
            return respVO;
        }).toList();
        return PageResult.of(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), res);
    }

    @Override
    public void changeStatus(Long userId) {
        UserDO user = userMapper.selectById(userId);
        if (user == null) {
            throw new exception(ErrorMsg.USER_NOT_EXIST);
        }
        user.setStatus(!user.getStatus());
        if (userMapper.updateById(user) < 1) {
            throw new exception(ErrorMsg.UPDATE_FAILED);
        }
    }

    @Override
    public int deleteByIds(Long[] ids) {
        return userMapper.deleteByIds(List.of(ids));
    }

    @Override
    public AdmUserPageRespVO get(Long userId) {
        UserDO userDO = userMapper.selectById(userId);
        if (userDO == null) {
            throw new exception(ErrorMsg.USER_NOT_EXIST);
        }
        AdmUserPageRespVO respVO = BeanUtil.toBean(userDO, AdmUserPageRespVO.class);
        respVO.setRoleName(roleMapper.getRoleByUserId(userId).getName());
        return respVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(UserAdmReqVO reqVO) {
        LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserDO::getUsername, reqVO.getUsername())
                .or().eq(UserDO::getPhone, reqVO.getPhone())
                .or().eq(UserDO::getEmail, reqVO.getEmail());
        queryWrapper.last("LIMIT 1");
        UserDO user = userMapper.selectOne(queryWrapper);
        if (user != null && user.getUsername().equals(reqVO.getUsername())) {
            throw new exception("用户名已被使用");
        }
        if (user != null && user.getPhone().equals(reqVO.getPhone())) {
            throw new exception("手机号已被使用");
        }
        if (user != null && user.getEmail().equals(reqVO.getEmail())) {
            throw new exception("邮箱已被使用");
        }
        if (!RoleEnum.validate(reqVO.getRole().toUpperCase(Locale.ROOT))) {
            throw new exception("角色不存在!");
        }
        RoleEnum userRole = RoleEnum.valueOf(reqVO.getRole().toUpperCase(Locale.ROOT));
        UserDO entity = BeanUtil.toBean(reqVO, UserDO.class);
        if (StringUtils.isNotBlank(reqVO.getAvatar())) {
            entity.setAvatar(fileUtil.saveFile(reqVO.getAvatar()));
        }
        int insert = userMapper.insert(entity);
        if (insert < 1) {
            throw new exception(ErrorMsg.INSERT_FAILED);
        }
        // 分配角色
        LambdaQueryWrapper<RoleDO> roleQueryWrapper = new LambdaQueryWrapper<>();
        roleQueryWrapper.eq(RoleDO::getName, userRole.name());
        RoleDO role = roleMapper.selectOne(roleQueryWrapper);
        if (role == null) {
            role = RoleDO.builder()
                    .name(userRole.name())
                    .label(userRole.getLabel())
                    .build();
            insert = roleMapper.insert(role);
            if (insert < 1) {
                throw new exception("分配角色失败!");
            }
        }
        boolean roleRel = roleMapper.insertUserRoleRel(entity.getId(), role.getId());
        if (!roleRel) {
            throw new exception("分配角色失败!");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(UserAdmReqVO reqVO) {
        if (reqVO.getId() == null) {
            throw new exception("id不能为空");
        }
        LambdaQueryWrapper<UserDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(UserDO::getId, reqVO.getId())
                .and(q -> q.eq(UserDO::getPhone, reqVO.getPhone())
                        .or().eq(UserDO::getEmail, reqVO.getEmail()));
        queryWrapper.last("LIMIT 1");
        UserDO user = userMapper.selectOne(queryWrapper);
        if (user != null && user.getPhone().equals(reqVO.getPhone())) {
            throw new exception("手机号已被绑定");
        }
        if (user != null && user.getEmail().equals(reqVO.getEmail())) {
            throw new exception("邮箱已被绑定");
        }
        UserDO entity = BeanUtil.copyProperties(reqVO, UserDO.class, "avatar");
        if (StringUtils.isNotBlank(reqVO.getAvatar())) {
            entity.setAvatar(fileUtil.saveFile(reqVO.getAvatar()));
        }
        int update = userMapper.updateById(entity);
        if (update < 1) {
            throw new exception(ErrorMsg.UPDATE_FAILED);
        }
    }
}
